<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 

class App {
	
	private static $ci = null;
	
	private static $_registry = array();

	public function __construct() {
		self::$ci =& get_instance();
		self::$ci->load->database();
		self::helper('blog');
		self::helper('url');
		self::helper('form');
		self::lib('session');
	}
	
	public static function lib($name) {
		if (!isset(self::$ci->$name))
			self::$ci->load->library($name);
		return self::$ci->$name;
	}
	
	public static function model($name) {
		$name .= '_model';
		if (!isset(self::$ci->$name))
			self::$ci->load->model($name);
		return self::$ci->$name;
	}
	
	public static function helper($name) {
		self::$ci->load->helper($name);
	}
	
	public static function view($tpl, $data) {
		self::$ci->load->view($tpl, $data);
	}
	
	public static function get($name = null) {
		return self::$ci->input->get($name);
	}
	
	public static function post($name = null) {
		return self::$ci->input->post($name);
	}
	
	/**
	 * Retrieve a value from session by a key
	 * Set a new variable in session
	 * Unset a variable from session by key
	 *
	 * @param string $key
     * @param mixed $value
	 * @return mixed
	 */
	public static function session() {
		$args = func_get_args();
		$n = count($args);
		
		if ($n == 2) {
			$name = $args[0];
			$value = $args[1];

			if ($value===null) {  // remove session
				self::$ci->session->unset_userdata($name);
			} else {  // set sesion value
				self::$ci->session->set_userdata(array($name => $value));
			}
		} elseif ($n == 1) { // retrieve session value
			$name = $args[0];
			return self::$ci->session->userdata($name);
		} elseif ($n == 0) { // retrieve all session values
			return self::$ci->session->all_userdata();
		}
	}

	/**
	 * Retrieve a value from uri segment
	 * Admin url: admin/controller/action/key1/val1/key2/val2
	 * Frontend url: controller/action/key1/val1/key2/val2
	 *
	 * @param string $name
	 * @return string|null
	 */
	public static function segment($name) {
		$ci = self::$ci;
		$params = $ci->uri->segment(1)=='admin' ?
			$ci->uri->uri_to_assoc(4) :
			$ci->uri->uri_to_assoc(3);
		return isset($params[$name]) ? $params[$name]: null;
	}
	
	/**
	 * Retrieve site url
	 * To get the base url, set the routePath & routeParams null
	 *
	 * @param string $routePath
	 * @param string $routeParams
	 * @return string
	 */
	public static function url($routePath = null, $routeParams = array()) {
		$url = base_url();
		
		if ($routePath !== null) {
			// replace wildcat in route path
			if (strstr($routePath, '/')!==false) {
				$segments = explode('/', $routePath);
				$tmp = array();
				for($i = 0; $i < count($segments); $i++) {
					if ($segments[$i] == '*') {
						$s = self::$ci->uri->segment($i+1);
						if ($s!==false) $tmp[] = $s;
					} else {
						$tmp[] = $segments[$i];
					}
				}
				$url .= implode('/', $tmp);
			} else {
				$url .= $routePath;
			}
		}
		
		// build segment
		$segments = '';
		foreach($routeParams as $k => $v) {
			if ($k[0] == '_') continue;
			$segments .= $k . '/' . $v . '/';
		}

		if (!empty($segments)) {
			$url = rtrim($url, '/') . '/';
			$segments = rtrim($segments, '/');
		}

		$url .= $segments;
		
		// build query string
		if (isset($routeParams['_query'])) {
			$params = array_filter($routeParams['_query']);
			if (!empty($params))
				$url .= '?' . http_build_query($params);
		}

		return $url;
	}
	
	public static function redirect($url) {
		redirect($url);
	}
	
	public static function db() {
		return self::$ci->db;
	}

	/**
	 * Retrieve object
	 *
	 * - class file is located in libraries folder
	 * - class file is auto-included by the autoload function in config.php
	 *
	 * @return mixed
	 */
	public static function object($class, $params=null) {
		return new $class($params);
	}

	/**
	 * Retrieve object singleton
	 *
	 * - class file is located in libraries folder
	 * - class file is auto-included by the autoload function in config.php
	 *
	 * @return mixed
	 */
	public static function objectSingleton($class, $params=null) {
		$registryKey = '_singleton/'.$class;
		if (!self::registry($registryKey)) {
			self::registry($registryKey, self::object($class, $params));
		}
		return self::registry($registryKey);
	}

	/**
	 * Retrieve a value from registry by a key
	 * Register a new variable
	 * Unregister a variable from register by key
	 *
	 * @param string $key
     * @param mixed $value
	 * @return mixed
	 */
	public static function registry() {
		$args = func_get_args();
		$n = count($args);
		
		if ($n == 2) {
			$name = $args[0];
			$value = $args[1];

			if ($value===null) {
				unset(self::$_registry[$name]);
			} else {
				self::$_registry[$name] = $value;
			}
		} elseif ($n == 1) {
			$name = $args[0];
			return isset(self::$_registry[$name]) ? self::$_registry[$name] : null;
		}
	}

	/**
	 * Retrieve config object
	 *
	 * @return string
	 */
	public static function config() {
		return self::objectSingleton('Core_Config');
		//return self::$ci->config->item($name);
	}
	
}
